Skip to content

fix(tasks,runners): critical requeue and finalization bugs#4008

Draft
cursor[bot] wants to merge 2 commits into
developfrom
cursor/critical-bug-investigation-d83e
Draft

fix(tasks,runners): critical requeue and finalization bugs#4008
cursor[bot] wants to merge 2 commits into
developfrom
cursor/critical-bug-investigation-d83e

Conversation

@cursor

@cursor cursor Bot commented Jul 6, 2026

Copy link
Copy Markdown

Summary

Automated bug inspection of develop at 5df51f03 found three critical correctness bugs in the remote-runner task lifecycle that remain unfixed. This PR cherry-picks the validated fixes (e854df0e, 7b9ffbea).

Recent commits since yesterday (branch override gate, access-key validation, custom-role privilege escalation fix, playbook path validation) were reviewed and look correct — no new critical regressions.

Bug 1: Duplicate dispatch on all-runners-busy requeue

Impact: When every runner is at capacity, ErrAllRunnersBusy enqueues the task while it still sits in the running set, then sends EventTypeRequeued from a defer. A concurrent queue tick can ClaimAndDequeue the task in that window and start a second dispatch on the same TaskRunner — duplicate execution.

Root cause: Running/active bookkeeping is released asynchronously via EventTypeRequeued instead of before enqueue.

Fix: Call onTaskStop and notify the pool synchronously before enqueueing, matching reconciler requeue paths.

Bug 2: Stopped → failed on runner after terminated_jobs

Impact: When the server returns terminated_jobs (task reassigned or finished while runner was offline), applyTerminatedJobs emergency-stops the job and sets stopped. When job.Run() unwinds with a kill error, the error path overwrites stopped with failed, reporting the wrong terminal status to the server.

Root cause: job_pool.go error handler unconditionally sets failed without checking if status is already terminal.

Fix: Add finalizeAfterRun that respects an already-finished status.

Bug 3: HA pool state leak in failTaskRunnerLost

Impact: In HA mode, when the reconciler wins the finalize lock but the DB already has a terminal status (runner reported on another node), failTaskRunnerLost returns without completing finalization. Pool/Redis state (running set, claims, End, autorun children) leaks.

Root cause: Early return on IsFinished() without calling finalizeRemoteTaskLocked. Also finalizeRemoteTaskLocked only checked End != nil under HA guard.

Fix: Complete finalization when DB is already terminal; harden offline requeue with pre-mutation DB re-check and rollback on persist failure.

Validation

  • go test ./services/tasks/... ./services/runners/... — all pass
  • New tests cover ErrAllRunnersBusy requeue ordering, finalizeAfterRun terminal-status preservation, HA reconciler finalization races
Open in Web View Automation 

cursoragent and others added 2 commits July 6, 2026 11:04
When every runner is at capacity, ErrAllRunnersBusy requeued tasks by
enqueueing them while they still sat in the running set, then sending
EventTypeRequeued from a defer. A periodic queue tick could
ClaimAndDequeue the task in that window and start a second dispatch on
the same TaskRunner.

Release running/active bookkeeping before enqueueing and notify the pool
synchronously, matching the reconciler requeue paths.

Co-authored-by: Denis Gukov <fiftin@outlook.com>
…finalization

Runner client: when applyTerminatedJobs emergency-stops a job and Run()
unwinds with an error, the error path overwrote stopped with failed.
Add finalizeAfterRun that respects an already-finished status.

HA reconciler: when failTaskRunnerLost wins the finalize lock but the DB
already has a terminal status, complete finalization instead of bailing
so pool/Redis state and autorun children are not leaked. Harden offline
requeue with a pre-mutation DB re-check and rollback on persist failure.

Co-authored-by: Denis Gukov <fiftin@outlook.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant